package com.system.appointment.service.impl;

import com.system.appointment.bean.*;
import com.system.appointment.dto.AppointmentDTO;
import com.system.appointment.dto.CallingMachineDTO;
import com.system.appointment.dto.PatientQueryDTO;
import com.system.appointment.dto.RefundDTO;
import com.system.appointment.feign.*;
import com.system.appointment.repository.AppointmentRepository;
import com.system.appointment.service.AppointmentService;
import com.system.appointment.service.AppointmentStatus;
import com.system.appointment.util.RandomOrderNoUtil;
import com.system.appointment.vo.AppointmentListVO;
import com.system.appointment.vo.AppointmentPatientDetailVO;
import com.system.appointment.vo.CallingMachineVo;
import com.system.appointment.vo.PatientVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @className: AppointmentServiceImpl
 * @description: 预约服务具体实现类
 * @author: Li Chuanwei
 * @date: 2023/11/12 15:40
 * @Company: Copyright [日期] by [作者或个人]
 **/

@Service
public class AppointmentServiceImpl extends AppointmentService {

    @Autowired
    private AppointmentRepository appointmentRepository;

    @Autowired
    private BillServiceFeign billServiceFeign;

    @Autowired
    private RegistrationPoolListServiceFeign registrationPoolListServiceFeign;

    @Autowired
    private PatientServiceFeign patientServiceFeign;

    @Autowired
    private DepartServiceFeign departServiceFeign;

    @Autowired
    private EmployeeServiceFeign employeeServiceFeign;

    @Autowired
    private ArrangementServiceFeign arrangementServiceFeign;

    @Autowired
    private QueueServiceFeign queueServiceFeign;

    @Autowired
    private PayServiceFeign payServiceFeign;
    @Override
    public boolean saveAppointment(Appointment appointment) {
        Appointment obj = appointmentRepository.save(appointment);
        if (obj != null) {
            return true;
        }
        return false;
    }

    @Override
    public boolean removeAppointmentById(int id) {
        if (appointmentRepository.existsById(id)) {
            appointmentRepository.deleteById(id);
            return true;
        }
        return false;
    }

    @Override
    public boolean modifyAppointment(Appointment appointment) {
        Appointment obj = appointmentRepository.save(appointment);
        if (obj != null) {
            return true;
        }
        return false;
    }

    @Override
    public Appointment getAppointmentById(int id) {
        if (appointmentRepository.existsById(id)) {
            return appointmentRepository.getReferenceById(id);
        }
        return null;
    }

    @Override
    public List<Appointment> listAllAppointments() {
        return appointmentRepository.findAll();
    }

    @Override
    public boolean cancelAppointment(int id) {
        System.out.println("取消订单");
        if(appointmentRepository.existsById(id)){
            Appointment appointment = appointmentRepository.getReferenceById(id);
            if(appointment.getState() == 1 || appointment.getState() == 2){
                if(registrationPoolListServiceFeign.releaseNumber(appointment.getPoolListId())){
                    if(appointment.getState() == 2){//如果状态为未就诊并且已经付款，则进行退款
                        RefundDTO refundDTO = new RefundDTO();
                        String dateTime = registrationPoolListServiceFeign.getTime(appointment.getPoolListId()).split(" ")[0];
                        refundDTO.setPrice(RefundStrategyFactory.createRefundStrategy(dateTime).calculateRefundAmount(appointment.getPrice()));
                        refundDTO.setOut_trade_no(appointment.getAppointmentNumber());
                        refundDTO.setOut_request_no("TK1");
                        payServiceFeign.appointmentRefund(refundDTO);
                    }
                    appointment.setState(7);
                    appointmentRepository.save(appointment);
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    protected boolean checkEligibility() {
        return true;
    }

    @Override
    protected Integer bookAppointment(AppointmentDTO appointmentDTO) {
        //锁号操作，如果锁号成功，则进行预约操作
        if (registrationPoolListServiceFeign.lockNumber(appointmentDTO.getPoolListId())) {
            Bill bill = new Bill();
            String number = RandomOrderNoUtil.createOrderId();//随机生成单号
            bill.setPatientId(appointmentDTO.getPatientId());
            bill.setBillNumber("BT" + number);
            bill.setPrice(appointmentDTO.getPrice());
            bill = billServiceFeign.saveGetBill(bill);
            if (bill != null) {
                Appointment appointment = new Appointment();
                appointment.setAppointmentNumber("AT" + number);
                appointment.setPatientId(appointmentDTO.getPatientId());
                appointment.setBillId(bill.getBillId());
                appointment.setPrice(appointmentDTO.getPrice());
                appointment.setPoolListId(appointmentDTO.getPoolListId());
                appointment = appointmentRepository.save(appointment);
                if (appointment != null) {
                    return appointment.getAppointmentId();
                }
            }
        }
        return -1;
    }

    @Override
    public AppointmentPatientDetailVO getPatientDetail(int id) {
        if (appointmentRepository.existsById(id)) {
            Appointment appointment = appointmentRepository.getReferenceById(id);
            if (appointment != null) {
                Integer arrangementId = registrationPoolListServiceFeign.getArrangementId(appointment.getPoolListId());
                Arrangement arrangement = arrangementServiceFeign.getHandle(arrangementId);
                Employee employee = employeeServiceFeign.getHandle(arrangement.getEmployeeId());
                AppointmentPatientDetailVO appointmentPatientDetailVO = new AppointmentPatientDetailVO();
                Patient patient = patientServiceFeign.getPatientById(appointment.getPatientId());
                Depart depart = departServiceFeign.getHandle(employee.getDepartmentId());
                if(depart.getAddress() == null)
                    depart.setAddress("未知");
                appointmentPatientDetailVO.setPname(patient.getPName());
                appointmentPatientDetailVO.setDepartment(depart.getDName());
                appointmentPatientDetailVO.setIdCardNumber(patient.getIdCardNumber());
                appointmentPatientDetailVO.setTelNumber(patient.getTelNumber());
                appointmentPatientDetailVO.setAppointmentTime(registrationPoolListServiceFeign.getTime(appointment.getPoolListId()));
                appointmentPatientDetailVO.setDepartmentAddress(depart.getAddress());
                appointmentPatientDetailVO.setAppointmentNumber(appointment.getAppointmentNumber());
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String createTime = appointment.getCreateTime().format(formatter);
                appointmentPatientDetailVO.setCreateTime(String.valueOf(createTime));
                appointmentPatientDetailVO.setServiceFee(String.valueOf(appointment.getPrice()));
                appointmentPatientDetailVO.setDoctorName(employee.getEName());
                appointmentPatientDetailVO.setDoctorLabel(employee.getETitle());
                appointmentPatientDetailVO.setAppointmentState(String.valueOf(appointment.getState()));
                return appointmentPatientDetailVO;
            }
        }
        return null;
    }

    @Override
    public boolean cancelUnpaidAppointment() {
        List<Appointment> appointments = appointmentRepository.findAllByState(1);
        LocalDateTime currentTime = LocalDateTime.now();
        for(Appointment appointment:appointments){
            if (appointment.getState() == 1 && currentTime.minusMinutes(15).isAfter(appointment.getCreateTime())) {
                cancelAppointment(appointment.getAppointmentId());
            }
        }
        return true;
    }

    @Override
    public Integer paySuccess(String outTradeNo) {
        Appointment appointment = appointmentRepository.findByAppointmentNumber(outTradeNo);
        if (appointment!= null) {
            appointment.setState(2);
            appointmentRepository.save(appointment);
            return appointment.getAppointmentId();
        }
        return -1;
    }

    @Override
    public List<AppointmentListVO> getAppointmentList(PatientQueryDTO patientQueryDTO) {
        List<Appointment> appointments =appointmentRepository.findAllByPatientId(patientQueryDTO.getPatientId());
        String[] stateArray = patientQueryDTO.getState().split(",");
        // 将数组转换为ArrayList
        List<String> stateList = Arrays.asList(stateArray);
        List<AppointmentListVO> appointmentListVOS = new ArrayList<>();
        for(Appointment appointment:appointments){
            if(stateList.contains(String.valueOf(appointment.getState()))){
                AppointmentListVO appointmentListVO = new AppointmentListVO();
                appointmentListVO.setId(appointment.getAppointmentId());
                Integer arrangementId = registrationPoolListServiceFeign.getArrangementId(appointment.getPoolListId());
                Arrangement arrangement = arrangementServiceFeign.getHandle(arrangementId);
                Employee employee = employeeServiceFeign.getHandle(arrangement.getEmployeeId());
                Depart depart = departServiceFeign.getHandle(employee.getDepartmentId());

                appointmentListVO.setDoctorName(employee.getEName());
                appointmentListVO.setDepartmentName(depart.getDName());
                appointmentListVO.setAppointmentTime(registrationPoolListServiceFeign.getTime(appointment.getPoolListId()));
                appointmentListVO.setStatus(AppointmentStatus.getStatusText(appointment.getState()));
                appointmentListVOS.add(appointmentListVO);
            }
        }
        return appointmentListVOS;
    }

    @Override
    public CallingMachineVo getAppointmentByPatientIdCardNumber(CallingMachineDTO callingMachineDTO) {
        Appointment appointment = appointmentRepository.findByAppointmentNumber(callingMachineDTO.getNumber());
        CallingMachineVo callingMachineVo = new CallingMachineVo();
        if(appointment==null){
            if(callingMachineDTO.getNumber().equals("")){
                callingMachineVo.setMessage("请输入号码");
            }else {
                PatientVo patientVo = patientServiceFeign.getPatientByIdCardNumber(callingMachineDTO.getNumber());
                if(patientVo!=null){
                    appointment = appointmentRepository.findByPatientId(patientVo.getPatientId());
                }
                else{
                    callingMachineVo.setMessage("号码错误");
                }
            }
        }
        if(appointment!=null){
            Integer arrangementId = registrationPoolListServiceFeign.getArrangementId(appointment.getPoolListId());
            Arrangement arrangement = arrangementServiceFeign.getHandle(arrangementId);
            Employee employee = employeeServiceFeign.getHandle(arrangement.getEmployeeId());
            Depart depart = departServiceFeign.getHandle(employee.getDepartmentId());
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            if(depart.getDepartId()==callingMachineDTO.getDepartmentId()){
                String time = registrationPoolListServiceFeign.getTime(appointment.getPoolListId()).split(" ")[0];
                if(LocalDate.now().isEqual(LocalDate.parse(time))){
                    switch (appointment.getState()){
                        case 1:  callingMachineVo.setMessage("您的预约未付款，请去前台付款");break;
                        case 2: callingMachineVo.setAppointmentNumber(appointment.getAppointmentNumber());
                            callingMachineVo.setPName(patientServiceFeign.getPatientName(appointment.getPatientId()));
                            callingMachineVo.setMessage("签到成功");
                            Queue queue = new Queue();
                            queue.setAppointmentId(appointment.getAppointmentId());
                            queue.setPoollstId(appointment.getPoolListId());
                            queue.setEmployeeId(arrangement.getEmployeeId());
                            queue.setConsultationId(arrangement.getConsultationId());
                            queueServiceFeign.saveHandle(queue);
                            appointment.setState(3);
                            this.modifyAppointment(appointment);
                            break;
                        case 3:    callingMachineVo.setMessage("请勿重复签到");break;
                        case 4:    callingMachineVo.setMessage("请勿重复签到");break;
                        case 5:    callingMachineVo.setMessage("请勿重复签到");break;
                        case 6:    callingMachineVo.setMessage("请勿重复签到");break;
                        case 7:    callingMachineVo.setMessage("您的预约已取消");break;
                        case 8:    callingMachineVo.setMessage("您已过号，已为您重新签到");break;
                        case 9:    callingMachineVo.setMessage("请您前往前台挂号");break;
                        default:    callingMachineVo.setMessage("号码有问题");break;
                    }
                }
                else{
                    callingMachineVo.setMessage("您在今天没有该科室的挂号信息");
                }
            }
            else{
                callingMachineVo.setMessage("您的挂号不属于该科室");
            }
        }
        return callingMachineVo;
    }
}
